// hooks/useRequest/core.ts
import { ref, reactive, onUnmounted } from 'vue';
import { RequestOptions, RequestResult, RequestTask } from './types';
import { resolveURL } from './config';

// 请求任务映射
const requestTaskMap = new Map<string, RequestTask>();
// 待取消请求ID集合
const pendingCancellation = new Set<string>();

/**
 * 生成唯一请求ID
 */
const generateRequestId = (): string => {
	return `${Date.now()}_${Math.random().toString(36).slice(2)}`;
};

/**
 * 创建请求任务
 * @param url 请求地址
 * @param options 请求配置
 * @returns 请求Promise和任务对象
 */
export const createRequestTask = <T>(url: string, options: RequestOptions): {
	promise: Promise<T>,
	task: RequestTask
} => {
	// 如果请求在开始前就已被标记为取消
	if (options.requestId && pendingCancellation.has(options.requestId)) {
		pendingCancellation.delete(options.requestId);
		return {
			promise: Promise.reject(new Error('request:fail abort')),
			task: { abort: () => { } }
		};
	}

	let requestTask: any = null;

	const promise = new Promise<T>((resolve, reject) => {
		// 解析URL，添加baseURL
		const resolvedUrl = resolveURL(url);

		requestTask = uni.request({
			url: resolvedUrl,
			method: options.method || 'GET',
			data: options.params || options.data,
			header: options.headers,
			timeout: options.timeout,
			success: (res: any) => {
				// 这里可以根据项目需求处理响应数据
				if (res.statusCode >= 200 && res.statusCode < 300) {
					resolve(res.data as T);
				} else {
					reject(new Error(`Request failed with status code ${res.statusCode}`));
				}
			},
			fail: (err: any) => {
				reject(new Error(err.errMsg || 'Request failed'));
			},
			complete: () => {
				// 请求完成后从映射中删除
				if (options.requestId) {
					requestTaskMap.delete(options.requestId);
				}
			}
		});
	});

	const task: RequestTask = {
		abort: () => {
			if (requestTask && typeof requestTask.abort === 'function') {
				requestTask.abort();
			}
		}
	};

	// 将任务添加到映射中
	if (options.requestId) {
		requestTaskMap.set(options.requestId, task);
	}

	return { promise, task };
};

/**
 * 取消请求
 * @param requestId 请求ID
 */
export const cancelRequest = (requestId: string): void => {
	const task = requestTaskMap.get(requestId);
	if (task) {
		task.abort();
		requestTaskMap.delete(requestId);
	} else {
		pendingCancellation.add(requestId);
	}
};

/**
 * 取消所有请求
 */
export const cancelAllRequests = (): void => {
	requestTaskMap.forEach(task => {
		task.abort();
	});
	requestTaskMap.clear();
};

/**
 * 核心请求Hook
 * @param url 请求地址或请求函数
 * @param initialOptions 初始请求配置
 * @returns 请求结果
 */
export const useRequestCore = <T = any>(
	url: string | ((params?: any) => string),
	initialOptions: RequestOptions = {}
): RequestResult<T> => {
	// 响应式状态
	const data = ref<T>();
	const loading = ref(false);
	const error = ref<Error | null>(null);
	const polling = ref(false);

	// 内部状态
	const options = reactive({
		...initialOptions,
		requestId: initialOptions.requestId || generateRequestId()
	});

	let pollingTimer: ReturnType<typeof setTimeout> | null = null;
	let pollingCount = 0;
	let currentParams: any = undefined;

	// 执行请求
	const execute = async (params?: any): Promise<T> => {
		// 合并参数
		const mergedParams = { ...options.params, ...params };
		currentParams = mergedParams;

		// 构建请求URL
		const requestUrl = typeof url === 'function' ? url(mergedParams) : url;

		// 显示loading
		if (options.showLoading) {
			uni.showLoading({
				title: options.loadingText || '加载中...',
				mask: true
			});
		}

		loading.value = true;
		error.value = null;

		try {
			const { promise, task } = createRequestTask<T>(requestUrl, {
				...options,
				params: mergedParams
			});

			const result = await promise;
			data.value = result;
			return result;
		} catch (err: any) {
			const isAbort = err.message && err.message.includes('abort');
			error.value = err;
			// 只有在不是用户主动取消的情况下才进行重试和提示
			if (!isAbort) {
				// 错误提示
				if (options.showError) {
					uni.showToast({
						title: err.message || '请求失败',
						icon: 'none'
					});
				}

				// 重试机制
				if (options.retryCount && options.retryCount > 0) {
					options.retryCount--;
					await new Promise(resolve => setTimeout(resolve, options.retryInterval || 1000));
					return execute(params);
				}
			}

			throw err;
		} finally {
			loading.value = false;

			// 隐藏loading
			if (options.showLoading) {
				uni.hideLoading();
			}

			// 如果设置了轮询，则在请求完成后启动轮询
			if (options.pollingInterval && options.pollingInterval > 0) {
				startPolling();
			}
		}
	};

	// 开始轮询
	const startPolling = () => {
		if (polling.value || !options.pollingInterval || options.pollingInterval <= 0) return;

		polling.value = true;
		pollingCount = 0;

		const poll = async () => {
			if (!polling.value) return;

			try {
				await run(currentParams);
			} catch (err) {
				// 轮询错误处理
			}

			pollingCount++;

			// 检查是否达到最大轮询次数
			if (options.pollingMaxCount && pollingCount >= options.pollingMaxCount) {
				stopPolling();
				return;
			}

			// 设置下一次轮询
			pollingTimer = setTimeout(poll, options.pollingInterval);
		};

		poll();
	};

	// 停止轮询
	const stopPolling = () => {
		polling.value = false;
		if (pollingTimer) {
			clearTimeout(pollingTimer);
			pollingTimer = null;
		}
	};

	// 运行请求
	const run = async (params?: any): Promise<T> => {
		return execute(params);
	};

	// 刷新请求
	const refresh = (): Promise<T> => {
		return run(currentParams);
	};

	// 取消请求
	const cancel = () => {
		cancelRequest(options.requestId!);
	};

	// 更新参数
	const updateParams = (params: any) => {
		options.params = { ...options.params, ...params };
	};

	// 更新配置
	const updateOptions = (newOptions: Partial<RequestOptions>) => {
		Object.assign(options, newOptions);
	};

	// 清除缓存 (在缓存模块中实现)
	const clearCache = () => {
		// 将在缓存模块中实现
	};

	// 重置状态
	const reset = () => {
		data.value = undefined;
		error.value = null;
		stopPolling();
	};

	// 组件卸载时清理
	onUnmounted(() => {
		stopPolling();
		cancel();
	});

	return {
		data,
		loading,
		error,
		polling,
		run,
		cancel,
		refresh,
		clearCache,
		startPolling,
		stopPolling,
		updateParams,
		updateOptions,
		reset
	};
};